<template>
  <div class="calendar">
    <div class="calendar-top">
      <div class="monthChoice">
        <a-space>
          <a-button shape="circle" @click="showMonthChnage('last')">
            <icon-left />
          </a-button>
          <div style="font-size: 20px">
            {{ showMonth.format('YYYY 年 MM 月') }}
          </div>
          <a-button shape="circle" @click="showMonthChnage('next')">
            <icon-right />
          </a-button>
          <a-button
            @click="showMonth = nowDate"
            size="mini"
            v-if="nowDate.month() !== showMonth.month()"
          >
            今天
          </a-button>
        </a-space>
      </div>
      <a-grid :cols="7" :colGap="0" :rowGap="0">
        <a-grid-item
          v-for="(item, index) in ['一', '二', '三', '四', '五', '六', '日']"
          class="weekName"
          :key="index"
        >
          周{{ item }}
        </a-grid-item>
      </a-grid>
    </div>
    <a-grid :cols="7" :colGap="0" :rowGap="0" class="grid">
      <a-grid-item
        class="grid-item"
        v-for="item in dayList"
        :key="item.millisecond"
      >
        <div
          class="title"
          :class="{
            today:
              (!choiceList && item.dateJs.isSame(nowDate)) ||
              isChoice(item.dateJs),
            lastMonth: item.type === 'lastMonth',
            nextMonth: item.type === 'nextMonth',
          }"
        >
          {{ item.dateJs.date() }}
        </div>
        <slot
          name="day"
          :dateJs="item.dateJs"
          :type="item.type"
          :millisecond="item.millisecond"
        />
      </a-grid-item>
    </a-grid>
  </div>
</template>

<script setup lang="ts">
  import { reactive, computed, ref, nextTick } from 'vue';
  import Dayjs from 'dayjs';

  const props = withDefaults(
    defineProps<{
      choiceList?: any[];
    }>(),
    {}
  );

  let nowDate = Dayjs().startOf('d');
  let showMonth = ref(nowDate);
  let showMonthChnage = (mode: 'last' | 'next') => {
    showMonth.value =
      mode === 'last'
        ? showMonth.value.subtract(1, 'M')
        : showMonth.value.add(1, 'M');
  };

  let isChoice = (date: any) => {
    return props.choiceList?.some((item) => {
      return item.isSame(date, 'day');
    });
  };

  /**
   * 生成日历日期列表
   * 从上个月开始,生成上个月末尾几天
   * 生成本月所有日期
   * 生成下个月开始几天
   * 这样可以完整显示一个月的日期
   */
  let dayList = computed(() => {
    let monthStart = showMonth.value.startOf('M');
    let monthEnd = showMonth.value.endOf('M').startOf('D');
    let list: any = [];

    let startNum = monthStart.day() ? monthStart.day() - 1 : 6;
    for (let i = 0; i < startNum; i += 1) {
      let dateJs = monthStart.subtract(i + 1, 'd');
      list.splice(0, 0, {
        dateJs,
        millisecond: dateJs.valueOf(),
        type: 'lastMonth',
      });
    }

    let centerNum = monthEnd.toDate().getDate();
    for (let i = 0; i < centerNum; i += 1) {
      let dateJs = monthStart.add(i, 'd');
      list.push({
        dateJs,
        millisecond: dateJs.valueOf(),
        type: 'thisMonth',
      });
    }

    let endNum = 7 - (monthEnd.day() || 7);
    for (let i = 0; i < endNum; i += 1) {
      let dateJs = monthEnd.add(i + 1, 'd');
      list.push({
        dateJs,
        millisecond: dateJs.valueOf(),
        type: 'nextMonth',
      });
    }
    return list;
  });

  defineExpose({
    changeShowMonth: (date: Date) => {
      showMonth.value = Dayjs(date);
    },
  });
</script>

<style lang="less" scoped>
  .calendar {
    &-top {
      border-top: 1px var(--color-neutral-3) solid;
      border-left: 1px var(--color-neutral-3) solid;
      border-right: 1px var(--color-neutral-3) solid;
    }
    .monthChoice {
      padding-left: 20px;

      padding-top: 20px;
    }
    .weekName {
      padding: 15px;
      color: var(--color-neutral-8);
    }
    .grid {
      border-top: 1px var(--color-neutral-3) solid;
      border-left: 1px var(--color-neutral-3) solid;
      &-item {
        padding: 10px;
        border-bottom: 1px var(--color-neutral-3) solid;
        border-right: 1px var(--color-neutral-3) solid;
        .title {
          line-height: 24px;
          width: 24px;
          border-radius: 12px;
          text-align: center;
          margin-bottom: 10px;
        }
        .today {
          background: rgb(var(--arcoblue-6));
          color: #fff;
        }
        .lastMonth {
          color: var(--color-neutral-4);
        }

        .nextMonth {
          color: var(--color-neutral-4);
        }
      }
    }
  }
</style>
